function PicTerrain( baseUri, width, height, row, col, tileW, tileH){
    tileW = tileW || 256;
    tileH = tileH || 256;
    
    row = row || math.floor( height / tileH) + 1;
    col = col || math.floor( height / tileW) + 1;
    
    this._baseUri = baseUri;
    // world coor
    this.x = 0;
    this.y = 0;
    this.w = width;
    this.h = height;
    this._row = row;
    this._col = col;
    this._tileW = tileW;
    this._tileH = tileH; 
    this._visible = rect2d.create( 0, 0, 800, 600);
    this._vStartR = -1;
    this._vStartC = -1;
    this._images = new Array();
}

PicTerrain.prototype = {
setPos : function( x, y) {
    this.x = x;
    this.y = y;
},

translateVisible : function( dx, dy) {
	var x = this._visible.x + dx;
	var y = this._visible.y + dy;
	if ( x < 0) x = 0;
	if ( y < 0) y = 0;
	this.setVisibleArea( x, y, this._visible.w, this._visible.h);
},

setVisibleArea : function( rect) {
    var localX = rect.x - this.x;
    var localY = rect.y - this.y;
    
    if ( localX < 0) {
        this._visible.w = rect.w + localX;
        this._visible.x = 0;
    }
    else {
        this._visible.w = rect.w > this.w ? this.w : rect.w;
        this._visible.x = rect.x;
    }
        
    if ( localY < 0) {
        this._visible.h = h + localX;
        this._visible.y = 0;
    }
    else {
        this._visible.h = rect.h > this.h ? this.h : rect.h;
        this._visible.y = y;
    }
    
    var r = Math.floor( this._visible.y / this._tileH);
    var c = Math.floor( this._visible.x / this._tileW);
    //if ( r == this._vStartR && c == this._vStartC)
        //return;
    this._vStartR = r;
    this._vStartC = c;
        
    var endR = Math.floor( (this._visible.y + this._visible.h) / this._tileH);
    var endC = Math.floor( (this._visible.x + this._visible.w) / this._tileW);
    var thisTrn = this;
    for ( ; r <= endR; ++r) {
        var index = r * this._col;
        for ( c = this._vStartC; c <= endC; ++c) {
            if ( (typeof this._images[index + c]) != 'undefined')
                continue;
            var img = new Image();
            img.isOk = false;
            this._images[index + c] = img;
            img.onload = function() {
                this.isOk = true;
            }
            img.src = this._baseUri + String( r) + "_" + String( c) + ".jpg"
        }
    }
        
},

draw : function( context) {
    var x = 0;
    var y = 0;
    var w, h;
    var endR = Math.floor( (this._visible.y + this._visible.h) / this._tileW);
    var endC = Math.floor( (this._visible.x + this._visible.w) / this._tileH);
    var sx, sy;
    for ( var r = this._vStartR; r <= endR; ++r) {
        if ( r == this._vStartR) {
            sy = this._visible.y - this._tileH * r;
        }
        else {
            sy = 0;
        }
        h = this._tileH;
        if ( y + h > this.h)
            h = this.h - y;
        if ( sy + h > this._tileH)
        		h = this._tileH - sy;
        
        var imgIndex = r * this._col + this._vStartC; 
        x = 0;   
        for ( var c = this._vStartC; c <= endC; ++c, ++imgIndex) {
            if ( c == this._vStartC) {
                sx = this._visible.x - this._tileW * c;
            }
            else {
                sx = 0;
            }
            w = this._tileW;
            if ( x + w > this.w)
                w = this.w - x;
            if ( sx + w > this._tileW)
            		w = this._tileW - sx;
                
            var img = this._images[imgIndex];
            if ( typeof img == 'undefined')
                continue;
            if ( !img.isOk)
                continue;
            context.drawImage( img, sx, sy, w, h, this.x + x, this.y + y, w, h);
            x += w;
        }
        
        y += h;
    }
    
},

}   // end PicTerrain.prototype